package com.sihai.core;

import java.io.Serializable;
import java.util.LinkedHashMap;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.criterion.DetachedCriteria;
import org.hibernate.criterion.Order;

/**
 * <code>Sort</code> 排序对象
 */
public class Sorter implements Serializable {

	/**
     *
     */
	private static final long serialVersionUID = 220961561706707123L;

	/**
	 * 排序类型
	 */
	private static enum Type {

		/**
		 * 升序
		 */
		ASCENDING,

		/**
		 * 降序
		 */
		DESCENDING
	}

	/**
	 * 排序指示对象
	 */
	private class Sort implements Serializable {

		/**
         *
         */
		private static final long serialVersionUID = -6427876894629910120L;

		private String property;

		private Type type;

		public Sort(String property, Type type) {
			this.property = property;
			this.type = type;
		}

		public boolean isAscending() {
			return type == Type.ASCENDING;
		}

		@Override
		public String toString() {
			return property + " " + (type == Type.ASCENDING ? "asc" : "desc");
		}
	}

	private Map<String, Sort> sortMap = new LinkedHashMap<String, Sort>();

	/**
	 * 升序
	 * 
	 * @param property sort property
	 * @return this
	 */
	public Sorter asc(String property) {
		if (sortMap.containsKey(property)) {
			sortMap.remove(property);
		}
		sortMap.put(property, new Sort(property, Type.ASCENDING));
		return this;
	}

	/**
	 * 降序
	 * 
	 * @param property sort property
	 * @return this
	 */
	public Sorter desc(String property) {
		if (sortMap.containsKey(property)) {
			sortMap.remove(property);
		}
		sortMap.put(property, new Sort(property, Type.DESCENDING));
		return this;
	}

	/**
	 * 附加order语句到hql上
	 * 
	 * @param hql hql
	 * @return decorated hql
	 */
	public String decorate(String hql) {

		if (sortMap.isEmpty()) {
			return hql;
		}

		StringBuilder queryBuilder = new StringBuilder(hql);
		if (StringUtils.containsIgnoreCase(hql, "order by")) {
			queryBuilder.append(",").append(StringUtils.join(sortMap.values(), ","));
		} else {
			queryBuilder.append(" order by ").append(StringUtils.join(sortMap.values(), ","));
		}
		return queryBuilder.toString();
	}

	/**
	 * 附加order语句到 {@link org.hibernate.Criteria} 上
	 * 
	 * @param criteria {@link org.hibernate.Criteria}
	 * @return Criteria
	 */
	public Criteria decorate(Criteria criteria) {
		if (sortMap.isEmpty()) {
			return criteria;
		}

		for (Map.Entry<String, Sort> entry : sortMap.entrySet()) {
			String property = entry.getKey();
			Sort sort = entry.getValue();
			criteria.addOrder(sort.isAscending() ? Order.asc(property) : Order.desc(property));
		}
		return criteria;
	}

	public DetachedCriteria decorate(DetachedCriteria criteria) {
		if (sortMap.isEmpty()) {
			return criteria;
		}

		for (Map.Entry<String, Sort> entry : sortMap.entrySet()) {
			String property = entry.getKey();
			Sort sort = entry.getValue();
			criteria.addOrder(sort.isAscending() ? Order.asc(property) : Order.desc(property));
		}
		return criteria;
	}
}
